package com.ease.util.reflection {
   import com.ease.util.ProfilingManager;
   import com.ease.util.StringUtils;

   /**
    * Represents the member level (properties and methods) reflection info.
    */
   public class MemberReflectionInfo {
      /**
       * The member name.
       */
      public var name:String;

      /**
       * The declaring type name.
       */
      public var declaringTypeName:String;

      /**
       * The member's meta tags.
       */
      public var tagInfos:Vector.<TagReflectionInfo>;

      /**
       * Returns the tags objects corresponding to the given tag name.
       */
      public function getTagInfosByName(metatag:String):Vector.<TagReflectionInfo> {
         var result:Vector.<TagReflectionInfo> = new Vector.<TagReflectionInfo>();
         for each (var tagInfo:TagReflectionInfo in this.tagInfos) {
            if (tagInfo.name == metatag) {
               result.push(tagInfo);
            }
         }
         return result;
      }

      /**
       * Checks whether any of this member's tags has the given name.
       */
      public function hasTag(metatag:String):Boolean {
         for each (var tagInfo:TagReflectionInfo in this.tagInfos) {
            if (tagInfo.name == metatag) {
               return true;
            }
         }
         return false;
      }

      /**
       * Returns the arguments of the tag having the given name.
       */
      public function getTagArgInfos(metatag:String):Vector.<TagArgReflectionInfo> {
         var result:Vector.<TagArgReflectionInfo> =
            new Vector.<TagArgReflectionInfo>();
         for each (var tagInfo:TagReflectionInfo in this.tagInfos) {
            if (tagInfo.argInfos != null && tagInfo.name == metatag) {
               result = result.concat(tagInfo.argInfos);
            }
         }
         return result;
      }

      /**
       * Returns the argument values of the tags having the given name.
       * If a key is specified, then only arguments with the given key are considered.
       */
      public function getTagArgValues(metatag:String,
                                      key:String = null):Vector.<String> {
         var result:Vector.<String> = new Vector.<String>();
         var argInfos:Vector.<TagArgReflectionInfo> = getTagArgInfos(metatag);
         for each (var argInfo:TagArgReflectionInfo in argInfos) {
            if (key == null || StringUtils.isNullorEmpty(argInfo.key)
               || key == argInfo.key) {
               result.push(argInfo.value);
            }
         }
         return result;
      }

      /**
       * @see ProfilingManager.getObjectSize.
       */
      public function getNestedSize():int {
         var size1:int = ProfilingManager.instance.getObjectSize(this.name);
         //declaringTypeName is (mostly) shared in ReflectionManager.
         var size2:int = ProfilingManager.instance.getObjectSize(this.tagInfos);
         return  size1 + size2;
      }
   }
}